<!DOCTYPE html>
<html style="display: none;" lang="zh">
    <head>
    <meta charset="utf-8">
    <!--
        © Material Theme
        https://github.com/viosey/hexo-theme-material
        Version: 1.5.0 -->
    <script>
        window.materialVersion = "1.5.0"
        // Delete localstorage with these tags
        window.oldVersion = [
            'codestartv1',
            '1.3.4',
            '1.4.0',
            '1.4.0b1'
        ]
    </script>

    <!-- dns prefetch -->
    <meta http-equiv="x-dns-prefetch-control" content="on">



    <link rel="dns-prefetch" href="https://busuanzi.ibruce.info"/>












    <!-- Title -->
    
    <title>
        
            时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储 | 
        
        ElderJames&#39; Blog
    </title>

    <!-- Meta & Info -->
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <meta name="format-detection" content="telephone=no"/>
    <meta name="theme-color" content="#0097A7">
    <meta name="author" content="James Yeung">
    <meta name="description" itemprop="description" content="学习、札记、分享">
    <meta name="keywords" content="ElderJames&#39; Blog,.NET Core,InfluxDB">

    <!-- Import lsloader -->
    <script>(function(){window.lsloader={jsRunSequence:[],jsnamemap:{},cssnamemap:{}};lsloader.removeLS=function(key){try{localStorage.removeItem(key)}catch(e){}};lsloader.setLS=function(key,val){try{localStorage.setItem(key,val)}catch(e){}};lsloader.getLS=function(key){var val="";try{val=localStorage.getItem(key)}catch(e){val=""}return val};versionString="/*"+(window.materialVersion||"unknownVersion")+"*/";lsloader.clean=function(){try{var keys=[];for(var i=0;i<localStorage.length;i++){keys.push(localStorage.key(i))}keys.forEach(function(key){var data=lsloader.getLS(key);if(window.oldVersion){var remove=window.oldVersion.reduce(function(p,c){return p||data.indexOf("/*"+c+"*/")!==-1},false);if(remove){lsloader.removeLS(key)}}})}catch(e){}};lsloader.clean();lsloader.load=function(jsname,jspath,cssonload,isJs){if(typeof cssonload==="boolean"){isJs=cssonload;cssonload=undefined}isJs=isJs||false;cssonload=cssonload||function(){};var code;code=this.getLS(jsname);if(code&&code.indexOf(versionString)===-1){this.removeLS(jsname);this.requestResource(jsname,jspath,cssonload,isJs);return}if(code){var versionNumber=code.split(versionString)[0];if(versionNumber!=jspath){console.log("reload:"+jspath);this.removeLS(jsname);this.requestResource(jsname,jspath,cssonload,isJs);return}code=code.split(versionString)[1];if(isJs){this.jsRunSequence.push({name:jsname,code:code});this.runjs(jspath,jsname,code)}else{document.getElementById(jsname).appendChild(document.createTextNode(code));cssonload()}}else{this.requestResource(jsname,jspath,cssonload,isJs)}};lsloader.requestResource=function(name,path,cssonload,isJs){var that=this;if(isJs){this.iojs(path,name,function(path,name,code){that.setLS(name,path+versionString+code);that.runjs(path,name,code)})}else{this.iocss(path,name,function(code){document.getElementById(name).appendChild(document.createTextNode(code));that.setLS(name,path+versionString+code)},cssonload)}};lsloader.iojs=function(path,jsname,callback){var that=this;that.jsRunSequence.push({name:jsname,code:""});try{var xhr=new XMLHttpRequest;xhr.open("get",path,true);xhr.onreadystatechange=function(){if(xhr.readyState==4){if(xhr.status>=200&&xhr.status<300||xhr.status==304){if(xhr.response!=""){callback(path,jsname,xhr.response);return}}that.jsfallback(path,jsname)}};xhr.send(null)}catch(e){that.jsfallback(path,jsname)}};lsloader.iocss=function(path,jsname,callback,cssonload){var that=this;try{var xhr=new XMLHttpRequest;xhr.open("get",path,true);xhr.onreadystatechange=function(){if(xhr.readyState==4){if(xhr.status>=200&&xhr.status<300||xhr.status==304){if(xhr.response!=""){callback(xhr.response);cssonload();return}}that.cssfallback(path,jsname,cssonload)}};xhr.send(null)}catch(e){that.cssfallback(path,jsname,cssonload)}};lsloader.iofonts=function(path,jsname,callback,cssonload){var that=this;try{var xhr=new XMLHttpRequest;xhr.open("get",path,true);xhr.onreadystatechange=function(){if(xhr.readyState==4){if(xhr.status>=200&&xhr.status<300||xhr.status==304){if(xhr.response!=""){callback(xhr.response);cssonload();return}}that.cssfallback(path,jsname,cssonload)}};xhr.send(null)}catch(e){that.cssfallback(path,jsname,cssonload)}};lsloader.runjs=function(path,name,code){if(!!name&&!!code){for(var k in this.jsRunSequence){if(this.jsRunSequence[k].name==name){this.jsRunSequence[k].code=code}}}if(!!this.jsRunSequence[0]&&!!this.jsRunSequence[0].code&&this.jsRunSequence[0].status!="failed"){var script=document.createElement("script");script.appendChild(document.createTextNode(this.jsRunSequence[0].code));script.type="text/javascript";document.getElementsByTagName("head")[0].appendChild(script);this.jsRunSequence.shift();if(this.jsRunSequence.length>0){this.runjs()}}else if(!!this.jsRunSequence[0]&&this.jsRunSequence[0].status=="failed"){var that=this;var script=document.createElement("script");script.src=this.jsRunSequence[0].path;script.type="text/javascript";this.jsRunSequence[0].status="loading";script.onload=function(){that.jsRunSequence.shift();if(that.jsRunSequence.length>0){that.runjs()}};document.body.appendChild(script)}};lsloader.tagLoad=function(path,name){this.jsRunSequence.push({name:name,code:"",path:path,status:"failed"});this.runjs()};lsloader.jsfallback=function(path,name){if(!!this.jsnamemap[name]){return}else{this.jsnamemap[name]=name}for(var k in this.jsRunSequence){if(this.jsRunSequence[k].name==name){this.jsRunSequence[k].code="";this.jsRunSequence[k].status="failed";this.jsRunSequence[k].path=path}}this.runjs()};lsloader.cssfallback=function(path,name,cssonload){if(!!this.cssnamemap[name]){return}else{this.cssnamemap[name]=1}var link=document.createElement("link");link.type="text/css";link.href=path;link.rel="stylesheet";link.onload=link.onerror=cssonload;var root=document.getElementsByTagName("script")[0];root.parentNode.insertBefore(link,root)};lsloader.runInlineScript=function(scriptId,codeId){var code=document.getElementById(codeId).innerText;this.jsRunSequence.push({name:scriptId,code:code});this.runjs()};lsloader.loadCombo=function(jslist){var updateList="";var requestingModules={};for(var k in jslist){var LS=this.getLS(jslist[k].name);if(!!LS){var version=LS.split(versionString)[0];var code=LS.split(versionString)[1]}else{var version=""}if(version==jslist[k].path){this.jsRunSequence.push({name:jslist[k].name,code:code,path:jslist[k].path})}else{this.jsRunSequence.push({name:jslist[k].name,code:null,path:jslist[k].path,status:"comboloading"});requestingModules[jslist[k].name]=true;updateList+=(updateList==""?"":";")+jslist[k].path}}var that=this;if(!!updateList){var xhr=new XMLHttpRequest;xhr.open("get",combo+updateList,true);xhr.onreadystatechange=function(){if(xhr.readyState==4){if(xhr.status>=200&&xhr.status<300||xhr.status==304){if(xhr.response!=""){that.runCombo(xhr.response,requestingModules);return}}else{for(var i in that.jsRunSequence){if(requestingModules[that.jsRunSequence[i].name]){that.jsRunSequence[i].status="failed"}}that.runjs()}}};xhr.send(null)}this.runjs()};lsloader.runCombo=function(comboCode,requestingModules){comboCode=comboCode.split("/*combojs*/");comboCode.shift();for(var k in this.jsRunSequence){if(!!requestingModules[this.jsRunSequence[k].name]&&!!comboCode[0]){this.jsRunSequence[k].status="comboJS";this.jsRunSequence[k].code=comboCode[0];this.setLS(this.jsRunSequence[k].name,this.jsRunSequence[k].path+versionString+comboCode[0]);comboCode.shift()}}this.runjs()}})();</script>

    <!-- Import queue -->
    <script>function Queue(){this.dataStore=[];this.offer=b;this.poll=d;this.execNext=a;this.debug=false;this.startDebug=c;function b(e){if(this.debug){console.log("Offered a Queued Function.")}if(typeof e==="function"){this.dataStore.push(e)}else{console.log("You must offer a function.")}}function d(){if(this.debug){console.log("Polled a Queued Function.")}return this.dataStore.shift()}function a(){var e=this.poll();if(e!==undefined){if(this.debug){console.log("Run a Queued Function.")}e()}}function c(){this.debug=true}}var queue=new Queue();</script>

    <!-- Favicons -->
    <link rel="icon shortcut" type="image/ico" href="/img/favicon.png">
    <link rel="icon" sizes="192x192" href="/img/favicon.png">
    <link rel="apple-touch-icon" href="/img/favicon.png">

    <!--iOS -->
    <meta name="apple-mobile-web-app-title" content="Title">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="HandheldFriendly" content="True">
    <meta name="MobileOptimized" content="480">

    <!-- Add to homescreen for Chrome on Android -->
    <meta name="mobile-web-app-capable" content="yes">

    <!-- Add to homescreen for Safari on iOS -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-title" content="ElderJames&#39; Blog">

    <!-- Site Verification -->
    
    

    <!-- RSS -->
    
        
            <link rel=alternate type="application/rss+xml" href="rss.xml">
        
    

    <!--[if lte IE 9]>
        <link rel="stylesheet" href="/css/ie-blocker.css">

        
            <script src="/js/ie-blocker.zhCN.js"></script>
        
    <![endif]-->

    <!-- Import CSS -->
    
        <style id="material_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_css","/css/material.min.css?976y5g1pRWbrdcUItimr0g==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>
        <style id="style_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("style_css","/css/style.min.css?J9YGUOg9VFzvsUAJ8qxFsQ==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>

        
            
                <style id="prettify_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("prettify_css","/css/prettify.min.css?UDVrysExI1W3AEkuJF/bUQ==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>
                <style id="prettify_theme"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("prettify_theme","/css/prettify/github-v2.min.css?AfzKxt++K+/lhZBlSjnxwg==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>
            
        

    

    

    <!-- Config CSS -->

<!-- Other Styles -->
<style>
  body, html {
    font-family: Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
    overflow-x: hidden !important;
  }
  
  code {
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  }

  a {
    color: #00838F;
  }

  .mdl-card__media,
  #search-label,
  #search-form-label:after,
  #scheme-Paradox .hot_tags-count,
  #scheme-Paradox .sidebar_archives-count,
  #scheme-Paradox .sidebar-colored .sidebar-header,
  #scheme-Paradox .sidebar-colored .sidebar-badge{
    background-color: #0097A7 !important;
  }

  /* Sidebar User Drop Down Menu Text Color */
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:hover,
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:focus {
    color: #0097A7 !important;
  }

  #post_entry-right-info,
  .sidebar-colored .sidebar-nav li:hover > a,
  .sidebar-colored .sidebar-nav li:hover > a i,
  .sidebar-colored .sidebar-nav li > a:hover,
  .sidebar-colored .sidebar-nav li > a:hover i,
  .sidebar-colored .sidebar-nav li > a:focus i,
  .sidebar-colored .sidebar-nav > .open > a,
  .sidebar-colored .sidebar-nav > .open > a:hover,
  .sidebar-colored .sidebar-nav > .open > a:focus,
  #ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a {
    color: #0097A7 !important;
  }

  .toTop {
    background: #757575 !important;
  }

  .material-layout .material-post>.material-nav,
  .material-layout .material-index>.material-nav,
  .material-nav a {
    color: #757575;
  }

  #scheme-Paradox .MD-burger-layer {
    background-color: #757575;
  }

  #scheme-Paradox #post-toc-trigger-btn {
    color: #757575;
  }

  .post-toc a:hover {
    color: #00838F;
    text-decoration: underline;
  }

</style>


<!-- Theme Background Related-->

    <style>
      body {
        background-color: undefined;
      }

      /* blog_info bottom background */
      #scheme-Paradox .material-layout .something-else .mdl-card__supporting-text {
        background-color: #fff;
      }
    </style>




<!-- Fade Effect -->

    <style>
      .fade {
        transition: all 800ms linear;
        -webkit-transform: translate3d(0,0,0);
        -moz-transform: translate3d(0,0,0);
        -ms-transform: translate3d(0,0,0);
        -o-transform: translate3d(0,0,0);
        transform: translate3d(0,0,0);
        opacity: 1;
      }

      .fade.out{
        opacity: 0;
      }
    </style>


<!-- Import Font -->
<!-- Import Roboto -->

    <style>
        @font-face {
            font-family: Roboto;
            font-style: normal;
            font-weight: 300;
            src: url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-300.eot);
            src: local('Roboto'),local('Roboto-Normal'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-300.eot?#iefix) format('embedded-opentype'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-300.woff2) format('woff2'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-300.woff) format('woff'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-300.ttf) format('truetype'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-300.svg#Roboto) format('svg')
        }

        @font-face {
            font-family: Roboto;
            font-style: normal;
            font-weight: regular;
            src: url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-regular.eot);
            src: local('Roboto'),local('Roboto-Normal'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-regular.eot?#iefix) format('embedded-opentype'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-regular.woff2) format('woff2'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-regular.woff) format('woff'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-regular.ttf) format('truetype'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-regular.svg#Roboto) format('svg')
        }

        @font-face {
            font-family: Roboto;
            font-style: normal;
            font-weight: 500;
            src: url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-500.eot);
            src: local('Roboto'),local('Roboto-Normal'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-500.eot?#iefix) format('embedded-opentype'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-500.woff2) format('woff2'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-500.woff) format('woff'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-500.ttf) format('truetype'),url(https://lib.baomitu.com/fonts/roboto/roboto-v15-latin-500.svg#Roboto) format('svg')
        }
    </style>


<!-- Import Material Icon -->

    <link rel="stylesheet" href="//cdn.bootcss.com/material-design-icons/3.0.1/iconfont/material-icons.min.css">




    <!-- Import jQuery -->
    
        <script>lsloader.load("jq_js","https://cdn.bootcss.com/jquery/2.2.1/jquery.js", true)</script>
    

    <!-- The Open Graph protocol -->
    <meta property="og:url" content="https://yangshunjie.com">
    <meta property="og:type" content="blog">
    <meta property="og:title" content="时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储 | ElderJames&#39; Blog">
    <meta property="og:image" content="https://yangshunjie.com/img/favicon.png" />
    <meta property="og:description" content="学习、札记、分享">
    <meta property="og:article:tag" content=".NET Core"> <meta property="og:article:tag" content="InfluxDB"> 

    
        <meta property="article:published_time" content="Tue Sep 26 2017 00:44:01 GMT+0000" />
        <meta property="article:modified_time" content="Fri Dec 15 2017 09:43:03 GMT+0000" />
    

    <!-- The Twitter Card protocol -->
    <meta name="twitter:title" content="时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储 | ElderJames&#39; Blog">
    <meta name="twitter:description" content="学习、札记、分享">
    <meta name="twitter:image" content="https://yangshunjie.com/img/favicon.png">
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:url" content="https://yangshunjie.com" />

    <!-- Add canonical link for SEO -->
    
        <link rel="canonical" href="https://yangshunjie.com/influxdb-in-dotNEt-Core-2-ioc-and-repository-pattern.html" />
    

    <!-- Structured-data for SEO -->
    
        


<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "mainEntityOfPage": "https://yangshunjie.com/influxdb-in-dotNEt-Core-2-ioc-and-repository-pattern.html",
    "headline": "时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储",
    "datePublished": "Tue Sep 26 2017 00:44:01 GMT+0000",
    "dateModified": "Fri Dec 15 2017 09:43:03 GMT+0000",
    "author": {
        "@type": "Person",
        "name": "James Yeung",
        "image": {
            "@type": "ImageObject",
            "url": "https://avatars0.githubusercontent.com/u/7550366?v=4&amp;s=460"
        },
        "description": "学习/创作/分享"
    },
    "publisher": {
        "@type": "Organization",
        "name": "ElderJames&#39; Blog",
        "logo": {
            "@type":"ImageObject",
            "url": "/img/favicon.png"
        }
    },
    "keywords": ",.NET Core,InfluxDBElderJames&#39; Blog",
    "description": "学习、札记、分享",
}
</script>


    

    <!-- Analytics -->
    
    
    

    <!-- Custom Head -->
    

<link rel="stylesheet" href="/css/prism-vs.css" type="text/css">
<link rel="stylesheet" href="/css/prism-line-numbers.css" type="text/css"></head>


    
        <body id="scheme-Paradox" class="lazy">
            <div class="material-layout  mdl-js-layout has-drawer is-upgraded">
                

                <!-- Main Container -->
                <main class="material-layout__content" id="main">

                    <!-- Top Anchor -->
                    <div id="top"></div>

                    
                        <!-- Hamburger Button -->
                        <button class="MD-burger-icon sidebar-toggle">
                            <span class="MD-burger-layer"></span>
                        </button>
                    

                    <!-- Post TOC -->

    
    <!-- Back Button -->
    <!--
    <div class="material-back" id="backhome-div" tabindex="0">
        <a class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon"
           href="#" onclick="window.history.back();return false;"
           target="_self"
           role="button"
           data-upgraded=",MaterialButton,MaterialRipple">
            <i class="material-icons" role="presentation">arrow_back</i>
            <span class="mdl-button__ripple-container">
                <span class="mdl-ripple"></span>
            </span>
        </a>
    </div>
    -->


    <!-- Left aligned menu below button -->
    
    
    <button id="post-toc-trigger-btn"
        class="mdl-button mdl-js-button mdl-button--icon">
        <i class="material-icons">format_list_numbered</i>
    </button>

    <ul class="post-toc-wrap mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect" for="post-toc-trigger-btn" style="max-height:80vh; overflow-y:scroll;">
        <ol class="post-toc"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#NET-客户端"><span class="post-toc-number">1.</span> <span class="post-toc-text"><a href="#NET-&#x5BA2;&#x6237;&#x7AEF;" class="headerlink" title=".NET &#x5BA2;&#x6237;&#x7AEF;"></a>.NET &#x5BA2;&#x6237;&#x7AEF;</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#如何设计"><span class="post-toc-number">2.</span> <span class="post-toc-text"><a href="#&#x5982;&#x4F55;&#x8BBE;&#x8BA1;" class="headerlink" title="&#x5982;&#x4F55;&#x8BBE;&#x8BA1;"></a>&#x5982;&#x4F55;&#x8BBE;&#x8BA1;</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#Show-Code"><span class="post-toc-number">3.</span> <span class="post-toc-text"><a href="#Show-Code" class="headerlink" title="Show Code"></a>Show Code</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#InfluxDBOptions-cs"><span class="post-toc-number">3.0.1.</span> <span class="post-toc-text"><a href="#InfluxDBOptions-cs" class="headerlink" title="InfluxDBOptions.cs"></a>InfluxDBOptions.cs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#InfluxDbContext-cs"><span class="post-toc-number">3.0.2.</span> <span class="post-toc-text"><a href="#InfluxDbContext-cs" class="headerlink" title="InfluxDbContext.cs"></a>InfluxDbContext.cs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#IEventStorageRepository-cs"><span class="post-toc-number">3.0.3.</span> <span class="post-toc-text"><a href="#IEventStorageRepository-cs" class="headerlink" title="IEventStorageRepository.cs"></a>IEventStorageRepository.cs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#EventStorageRepository-cs"><span class="post-toc-number">3.0.4.</span> <span class="post-toc-text"><a href="#EventStorageRepository-cs" class="headerlink" title="EventStorageRepository.cs"></a>EventStorageRepository.cs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#EventStorageInfluxDBExtensions-cs"><span class="post-toc-number">3.0.5.</span> <span class="post-toc-text"><a href="#EventStorageInfluxDBExtensions-cs" class="headerlink" title="EventStorageInfluxDBExtensions.cs"></a>EventStorageInfluxDBExtensions.cs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#使用方法"><span class="post-toc-number">3.0.6.</span> <span class="post-toc-text"><a href="#&#x4F7F;&#x7528;&#x65B9;&#x6CD5;" class="headerlink" title="&#x4F7F;&#x7528;&#x65B9;&#x6CD5;"></a>&#x4F7F;&#x7528;&#x65B9;&#x6CD5;</span></a></li></ol></li></ol></li></ol>
    </ul>
    




<!-- Layouts -->

    <!-- Post Module -->
    <div class="material-post_container">

        <div class="material-post mdl-grid">
            <div class="mdl-card mdl-shadow--4dp mdl-cell mdl-cell--12-col">

                <!-- Post Header(Thumbnail & Title) -->
                
    <!-- Paradox Post Header -->
    
        <!-- Custom Thumbnail -->
        <div class="post_thumbnail-custom mdl-card__media mdl-color-text--grey-50" style="background-image:url(https://www.msolution.io/wp-content/uploads/2015/12/influxdb.png)">
    
            <p class="article-headline-p">
                时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储
            </p>
        </div>





                
                    <!-- Paradox Post Info -->
                    <div class="mdl-color-text--grey-700 mdl-card__supporting-text meta">

    <!-- Author Avatar -->
    <div id="author-avatar">
        <img src="https://avatars0.githubusercontent.com/u/7550366?v=4&s=460" width="44px" height="44px" alt="Author Avatar"/>
    </div>
    <!-- Author Name & Date -->
    <div>
        <strong>James Yeung</strong>
        <span>9月 26, 2017</span>
    </div>

    <div class="section-spacer"></div>

    <!-- Favorite -->
    <!--
        <button id="article-functions-like-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon btn-like">
            <i class="material-icons" role="presentation">favorite</i>
            <span class="visuallyhidden">favorites</span>
        </button>
    -->

    <!-- Qrcode -->
    
        <button id="article-functions-qrcode-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
    <i class="material-icons" role="presentation">devices other</i>
    <span class="visuallyhidden">devices other</span>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-functions-qrcode-button">
    <li class="mdl-menu__item">在其它设备中阅读本文章</li>
    
        <img src="">
    
</ul>

    

    <!-- Tags (bookmark) -->
    
    <button id="article-functions-viewtags-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
        <i class="material-icons" role="presentation">bookmark</i>
        <span class="visuallyhidden">bookmark</span>
    </button>
    <ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-functions-viewtags-button">
        <li class="mdl-menu__item">
        <a class="post_tag-link" href="/tags/NET-Core/">.NET Core</a></li><li class="mdl-menu__item"><a class="post_tag-link" href="/tags/InfluxDB/">InfluxDB</a>
    </ul>
    

    <!-- Share -->
    <button id="article-fuctions-share-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
    <i class="material-icons" role="presentation">share</i>
    <span class="visuallyhidden">share</span>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-fuctions-share-button">
    

    
        
            <!-- Busuanzi Views -->
            <a class="post_share-link" href="#">
                <li class="mdl-menu__item">
                    <span id="busuanzi_container_page_pv">
                        <span id="busuanzi_value_page_pv"></span>&nbsp;浏览量
                    </span>
                </li>
            </a>
        
    

    <!-- Share Weibo -->
    
        <a class="post_share-link" href="http://service.weibo.com/share/share.php?appkey=&title=时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储&url=https://yangshunjie.com/influxdb-in-dotNEt-Core-2-ioc-and-repository-pattern.html&pic=https://yangshunjie.com/img/favicon.png&searchPic=false&style=simple" target="_blank">
            <li class="mdl-menu__item">
                分享到微博
            </li>
        </a>
    

    <!-- Share Twitter -->
    

    <!-- Share Facebook -->
    

    <!-- Share Google+ -->
    

    <!-- Share LinkedIn -->
    

    <!-- Share QQ -->
    
        <a class="post_share-link" href="http://connect.qq.com/widget/shareqq/index.html?site=ElderJames&#39; Blog&title=时序数据库InfluxDB在.NET Core中的使用——（2）IoC和仓储模式实现事件存储&summary=学习、札记、分享&pics=https://yangshunjie.com/img/favicon.png&url=https://yangshunjie.com/influxdb-in-dotNEt-Core-2-ioc-and-repository-pattern.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 QQ
            </li>
        </a>
    

    <!-- Share Telegram -->
    
</ul>

</div>

                

                <!-- Post Content -->
                <div id="post-content" class="mdl-color-text--grey-700 mdl-card__supporting-text fade out">
    
        <script src="\assets\js\APlayer.min.js"> </script><p>我上一篇文章<a href="/influxdb-in-dotNEt-Core-1-Introduction.html">《InfluxDB在.NET Core中的使用——（1）InfluxDB简介》</a>中简单介绍了InfluxDB的相关概念，本文将继续介绍下半部分，就是在.NET Core中的使用方法。</p>
<h2 id="NET-客户端"><a href="#NET-客户端" class="headerlink" title=".NET 客户端"></a>.NET 客户端</h2><p>正因为InfluxDB是通过http请求来操作数据库，所以在.NET Core中使用很简单，只需要用HttpClient封装一个客户端、并且按照InfluxDB的数据结构去解析数据就行了。而且，已经有大神开发出了一个开源的可用于.NET Core的InfluxDB客户端项目 <a href="https://github.com/pootzko/InfluxData.Net" target="_blank" rel="noopener">InfluxData.Net</a> ，本文将利用这个客户端项目结合.NET Core自带的依赖注入框架和仓储模式，去封装一个事件存储的InfluxDB实现的类库。</p>
<h2 id="如何设计"><a href="#如何设计" class="headerlink" title="如何设计"></a>如何设计</h2><ol>
<li>把配置信息和InfluxDB客户端实例封装成一个服务。</li>
<li>用这个服务去实现原来定义的事件仓储接口。</li>
<li>遵循.NET Core的IoC风格，用<code>.Addxxx(option=&gt;{})</code>的方法配置数据库并且注册服务。</li>
</ol>
<h2 id="Show-Code"><a href="#Show-Code" class="headerlink" title="Show Code"></a>Show Code</h2><h4 id="InfluxDBOptions-cs"><a href="#InfluxDBOptions-cs" class="headerlink" title="InfluxDBOptions.cs"></a>InfluxDBOptions.cs</h4><p><code>InfluxDBOptions</code>类是一个配置类，主要有主机名<code>Host</code>( IP +端口号)，用户名 <code>UserName</code>，密码 <code>Password</code>，数据库名 <code>DatabaseName</code>。</p>
<pre class="line-numbers language-csharp"><code class="language-csharp"><span class="token comment" spellcheck="true">/// &lt;summary></span>
<span class="token comment" spellcheck="true">/// InfluxDB设置</span>
<span class="token comment" spellcheck="true">/// &lt;/summary></span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InfluxDBOptions</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Host <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">string</span> UserName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">string</span> Password <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">string</span> DatabaseName <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h4 id="InfluxDbContext-cs"><a href="#InfluxDbContext-cs" class="headerlink" title="InfluxDbContext.cs"></a>InfluxDbContext.cs</h4><p><code>InfluxDbContext</code> 类是InfluxDB上下文的意思，里面封装了 InfluxDbClient 的一些基本组成部分，数据库对象<code>Database</code>，客户端对象<code>Client</code>(不知道为啥要在<code>InfluxDbClient</code>内定义一个Client对象)，以及我们上面设计的配置对象<code>InfluxDBOptions</code>。</p>
<p>另外还有<code>EnsureDbCreated</code>、<code>WriteAsync</code>和<code>QueryAsync</code>，其中<code>EnsureDbCreated</code>是确保数据库已创建，而<code>WriteAsync</code>和<code>QueryAsync</code>是对原来客户端读写方法的简化。</p>
<pre class="line-numbers language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">InfluxDbContext</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">InfluxDbContext</span><span class="token punctuation">(</span>InfluxDBOptions options<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        Options <span class="token operator">=</span> options<span class="token punctuation">;</span>
        <span class="token keyword">var</span> client <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">InfluxDbClient</span><span class="token punctuation">(</span>options<span class="token punctuation">.</span>Host<span class="token punctuation">,</span> options<span class="token punctuation">.</span>UserName<span class="token punctuation">,</span> options<span class="token punctuation">.</span>Password<span class="token punctuation">,</span> InfluxDbVersion<span class="token punctuation">.</span>v_1_0_0<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>Client <span class="token operator">=</span> client<span class="token punctuation">.</span>Client<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>Database <span class="token operator">=</span> client<span class="token punctuation">.</span>Database<span class="token punctuation">;</span>
        <span class="token function">EnsureDbCreated</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> IDatabaseClientModule Database <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> IBasicClientModule Client <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> InfluxDBOptions Options <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">async</span> Task <span class="token function">EnsureDbCreated</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> dbs <span class="token operator">=</span> <span class="token keyword">await</span> Database<span class="token punctuation">.</span><span class="token function">GetDatabasesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>dbs<span class="token punctuation">.</span><span class="token function">All</span><span class="token punctuation">(</span>x <span class="token operator">=</span><span class="token operator">></span> x<span class="token punctuation">.</span>Name <span class="token operator">!=</span> Options<span class="token punctuation">.</span>DatabaseName<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">await</span> Database<span class="token punctuation">.</span><span class="token function">CreateDatabaseAsync</span><span class="token punctuation">(</span>Options<span class="token punctuation">.</span>DatabaseName<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">/// &lt;summary></span>
    <span class="token comment" spellcheck="true">/// 查询一个Serie</span>
    <span class="token comment" spellcheck="true">/// &lt;/summary></span>
    <span class="token comment" spellcheck="true">/// &lt;param name="query">&lt;/param></span>
    <span class="token comment" spellcheck="true">/// &lt;returns>&lt;/returns></span>
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span>Serie<span class="token operator">></span> <span class="token function">QueryAsync</span><span class="token punctuation">(</span><span class="token keyword">string</span> query<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token keyword">await</span> Client<span class="token punctuation">.</span><span class="token function">QueryAsync</span><span class="token punctuation">(</span>query<span class="token punctuation">,</span> Options<span class="token punctuation">.</span>DatabaseName<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> result<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">/// &lt;summary></span>
    <span class="token comment" spellcheck="true">/// 写入一个Point</span>
    <span class="token comment" spellcheck="true">/// &lt;/summary></span>
    <span class="token comment" spellcheck="true">/// &lt;param name="point">&lt;/param></span>
    <span class="token comment" spellcheck="true">/// &lt;returns>&lt;/returns></span>
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span>IInfluxDataApiResponse<span class="token operator">></span> <span class="token function">WriteAsync</span><span class="token punctuation">(</span>Point point<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">await</span> Client<span class="token punctuation">.</span><span class="token function">WriteAsync</span><span class="token punctuation">(</span>point<span class="token punctuation">,</span> Options<span class="token punctuation">.</span>DatabaseName<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h4 id="IEventStorageRepository-cs"><a href="#IEventStorageRepository-cs" class="headerlink" title="IEventStorageRepository.cs"></a>IEventStorageRepository.cs</h4><p><code>IEventStorageRepository</code>事件仓储接口是我设计的，只有两个方法，一个存储方法<code>Store</code>，一个查询方法<code>GetEvents</code>。有这个接口，我可以设计不同的ORM和数据库仓储，如已经实现的InMemory、EFCore、MongoDB、LiteDB，以及本篇的主角InfluxDB。</p>
<pre class="line-numbers language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IEventStorageRepository</span>
<span class="token punctuation">{</span>
    <span class="token keyword">void</span> <span class="token function">Store</span><span class="token punctuation">(</span>StoredEvent theEvent<span class="token punctuation">)</span><span class="token punctuation">;</span>

    IEnumerable<span class="token operator">&lt;</span>StoredEvent<span class="token operator">></span> <span class="token function">GetEvents</span><span class="token punctuation">(</span>Guid aggregateId<span class="token punctuation">,</span> <span class="token keyword">int</span> afterVersion <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>其中<code>StoredEvent</code>是一个继承了Event的特殊类，用来保存事件的相关属性。关于这个类的设计在这不是重点，可以到我的项目<a href="https://github.com/ElderJames/shriek-fx/blob/master/src/Shriek/Storage/StoredEvent.cs" target="_blank" rel="noopener">【Shriek】</a>中一窥究竟。</p>
<pre class="line-numbers language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">StoredEvent</span> <span class="token punctuation">:</span> Event
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">StoredEvent</span><span class="token punctuation">(</span>Event @<span class="token keyword">event</span><span class="token punctuation">,</span> <span class="token keyword">string</span> data<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        AggregateId <span class="token operator">=</span> @<span class="token keyword">event</span><span class="token punctuation">.</span>AggregateId<span class="token punctuation">;</span>
        Data <span class="token operator">=</span> data<span class="token punctuation">;</span>
        Version <span class="token operator">=</span> @<span class="token keyword">event</span><span class="token punctuation">.</span>Version<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token function">StoredEvent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>

    <span class="token punctuation">[</span>Key<span class="token punctuation">]</span>
    <span class="token keyword">public</span> <span class="token keyword">int</span> Id <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">protected</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">//事件的序列化json字符串</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Data <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h4 id="EventStorageRepository-cs"><a href="#EventStorageRepository-cs" class="headerlink" title="EventStorageRepository.cs"></a>EventStorageRepository.cs</h4><p>仓储实现类</p>
<pre class="line-numbers language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EventStorageRepository</span> <span class="token punctuation">:</span> IEventStorageRepository
<span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">readonly</span> InfluxDbContext _dbContext<span class="token punctuation">;</span>

    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">string</span> TableName <span class="token operator">=</span> <span class="token string">"events"</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">EventStorageRepository</span><span class="token punctuation">(</span>InfluxDbContext dbContext<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>_dbContext <span class="token operator">=</span> dbContext<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> IEnumerable<span class="token operator">&lt;</span>StoredEvent<span class="token operator">></span> <span class="token function">GetEvents</span><span class="token punctuation">(</span>Guid aggregateId<span class="token punctuation">,</span> <span class="token keyword">int</span> afterVersion <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">//查询语法跟普通sql是基本一致的，一定要注意，比价大小的字段一定是要在Fields中。Tags中的可以比较字符串是否相等</span>
        <span class="token comment" spellcheck="true">//另外，time是默认的索引，也可以比价大小</span>
        <span class="token keyword">var</span> query <span class="token operator">=</span> $<span class="token string">"SELECT * FROM {TableName} WHERE AggregateId='{aggregateId}' AND Version >= {afterVersion}"</span><span class="token punctuation">;</span>
        <span class="token keyword">var</span> result <span class="token operator">=</span> _dbContext<span class="token punctuation">.</span><span class="token function">QueryAsync</span><span class="token punctuation">(</span>query<span class="token punctuation">)</span><span class="token punctuation">.</span>Result<span class="token punctuation">;</span>

        <span class="token keyword">return</span> result <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">?</span> <span class="token keyword">new</span> <span class="token class-name">StoredEvent</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">:</span> <span class="token function">SerieToStoredEvent</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">Store</span><span class="token punctuation">(</span>StoredEvent theEvent<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">//实例化一个Point</span>
        <span class="token keyword">var</span> point <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Point</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token comment" spellcheck="true">//表名</span>
            Name <span class="token operator">=</span> TableName<span class="token punctuation">,</span>
            <span class="token comment" spellcheck="true">//用作索引的字段放到Tags里（只支持字符串，不能比较大小）</span>
            Tags <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dictionary</span><span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token punctuation">{</span><span class="token string">"AggregateId"</span><span class="token punctuation">,</span> theEvent<span class="token punctuation">.</span>AggregateId<span class="token punctuation">}</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token comment" spellcheck="true">//其他字段放到Fields里，参数值支持系统基本类型，不支持实体类</span>
            Fields <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dictionary</span><span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token punctuation">{</span><span class="token string">"Data"</span><span class="token punctuation">,</span> theEvent<span class="token punctuation">.</span>Data<span class="token punctuation">}</span><span class="token punctuation">,</span>
                <span class="token punctuation">{</span><span class="token string">"EventType"</span><span class="token punctuation">,</span> theEvent<span class="token punctuation">.</span>MessageType<span class="token punctuation">}</span><span class="token punctuation">,</span>
                <span class="token punctuation">{</span><span class="token string">"User"</span><span class="token punctuation">,</span> theEvent<span class="token punctuation">.</span>User<span class="token punctuation">}</span><span class="token punctuation">,</span>
                <span class="token punctuation">{</span><span class="token string">"Version"</span><span class="token punctuation">,</span> theEvent<span class="token punctuation">.</span>Version<span class="token punctuation">}</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token comment" spellcheck="true">//时间戳，默认是当前时间，此处用事件的时间戳比较准确</span>
            Timestamp <span class="token operator">=</span> theEvent<span class="token punctuation">.</span>Timestamp
        <span class="token punctuation">}</span><span class="token punctuation">;</span>

        <span class="token keyword">var</span> result <span class="token operator">=</span> _dbContext<span class="token punctuation">.</span><span class="token function">WriteAsync</span><span class="token punctuation">(</span>point<span class="token punctuation">)</span><span class="token punctuation">.</span>Result<span class="token punctuation">;</span>

        <span class="token comment" spellcheck="true">//结果返回是否写入成功</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>result<span class="token punctuation">.</span>Success<span class="token punctuation">)</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InfluxDataException</span><span class="token punctuation">(</span><span class="token string">"事件插入失败"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">//从Serie取数据转换为StoredEvent，需要一个个字段去取，所有字段都在Serie.Values中了</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> IEnumerable<span class="token operator">&lt;</span>StoredEvent<span class="token operator">></span> <span class="token function">SerieToStoredEvent</span><span class="token punctuation">(</span>Serie serie<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> serie<span class="token punctuation">.</span>Values<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>item <span class="token operator">=</span><span class="token operator">></span> <span class="token keyword">new</span> <span class="token class-name">StoredEvent</span>
        <span class="token punctuation">{</span>
            AggregateId <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>item<span class="token punctuation">[</span>serie<span class="token punctuation">.</span>Columns<span class="token punctuation">.</span><span class="token function">IndexOf</span><span class="token punctuation">(</span><span class="token string">"AggregateId"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            Version <span class="token operator">=</span> <span class="token keyword">int</span><span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>item<span class="token punctuation">[</span>serie<span class="token punctuation">.</span>Columns<span class="token punctuation">.</span><span class="token function">IndexOf</span><span class="token punctuation">(</span><span class="token string">"Version"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token comment" spellcheck="true">//这里的Replace是客户端的一个bug，已经提交Pull Request</span>
            Data <span class="token operator">=</span> item<span class="token punctuation">[</span>serie<span class="token punctuation">.</span>Columns<span class="token punctuation">.</span><span class="token function">IndexOf</span><span class="token punctuation">(</span><span class="token string">"Data"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Replace</span><span class="token punctuation">(</span><span class="token string">@"\", string.Empty),
            User = item[serie.Columns.IndexOf("</span>User"<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            MessageType <span class="token operator">=</span> item<span class="token punctuation">[</span>serie<span class="token punctuation">.</span>Columns<span class="token punctuation">.</span><span class="token function">IndexOf</span><span class="token punctuation">(</span><span class="token string">"EventType"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Replace</span><span class="token punctuation">(</span><span class="token string">@"\"</span><span class="token punctuation">,</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">)</span><span class="token punctuation">,</span>
            Timestamp <span class="token operator">=</span> DateTime<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>item<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h4 id="EventStorageInfluxDBExtensions-cs"><a href="#EventStorageInfluxDBExtensions-cs" class="headerlink" title="EventStorageInfluxDBExtensions.cs"></a>EventStorageInfluxDBExtensions.cs</h4><p>IoC注册及配置扩展类</p>
<pre class="line-numbers language-csharp"><code class="language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">EventStorageInfluxDBExtensions</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">AddInfluxDbEventStorage</span><span class="token punctuation">(</span><span class="token keyword">this</span> IServiceCollection services<span class="token punctuation">,</span> Action<span class="token operator">&lt;</span>InfluxDBOptions<span class="token operator">></span> optionAction<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> options <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">InfluxDBOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">optionAction</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><span class="token punctuation">;</span>

        services<span class="token punctuation">.</span><span class="token function">AddScoped</span><span class="token punctuation">(</span>x <span class="token operator">=</span><span class="token operator">></span> options<span class="token punctuation">)</span><span class="token punctuation">;</span>
        services<span class="token punctuation">.</span><span class="token generic-method function">AddScoped<span class="token punctuation">&lt;</span>InfluxDbContext<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        services<span class="token punctuation">.</span><span class="token generic-method function">AddScoped<span class="token punctuation">&lt;</span>IEventStorageRepository<span class="token punctuation">,</span> EventStorageRepository<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        services<span class="token punctuation">.</span><span class="token generic-method function">AddScoped<span class="token punctuation">&lt;</span>IMementoRepository<span class="token punctuation">,</span> MementoRepository<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        services<span class="token punctuation">.</span><span class="token generic-method function">AddScoped<span class="token punctuation">&lt;</span>IEventStorage<span class="token punctuation">,</span> SqlEventStorage<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h4 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h4><pre class="line-numbers language-csharp"><code class="language-csharp">    <span class="token keyword">var</span> services <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ServiceCollection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    services<span class="token punctuation">.</span><span class="token function">AddInfluxDbEventStorage</span><span class="token punctuation">(</span>options <span class="token operator">=</span><span class="token operator">></span>
    <span class="token punctuation">{</span>
        options<span class="token punctuation">.</span>Host <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">GetSection</span><span class="token punctuation">(</span><span class="token string">"InfluxDBConnection:Host"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Value<span class="token punctuation">;</span>
        options<span class="token punctuation">.</span>Password <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">GetSection</span><span class="token punctuation">(</span><span class="token string">"InfluxDBConnection:Password"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Value<span class="token punctuation">;</span>
        options<span class="token punctuation">.</span>UserName <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">GetSection</span><span class="token punctuation">(</span><span class="token string">"InfluxDBConnection:UserName"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Value<span class="token punctuation">;</span>
        options<span class="token punctuation">.</span>DatabaseName <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">GetSection</span><span class="token punctuation">(</span><span class="token string">"InfluxDBConnection:DatabaseName"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Value<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>配置文件<code>appsettings.json</code>中的配置</p>
<pre class="line-numbers language-json"><code class="language-json">  <span class="token property">"InfluxDBConnection"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"Host"</span><span class="token operator">:</span> <span class="token string">"http://localhost:8086"</span><span class="token punctuation">,</span>
    <span class="token property">"DatabaseName"</span><span class="token operator">:</span> <span class="token string">"event_store"</span><span class="token punctuation">,</span>
    <span class="token property">"UserName"</span><span class="token operator">:</span> <span class="token string">"admin"</span><span class="token punctuation">,</span>
    <span class="token property">"Password"</span><span class="token operator">:</span> <span class="token string">"admin"</span>
  <span class="token punctuation">}</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>大功告成~由于太晚了，我先贴上代码，有空再补上说明咯！</p>

        
                <blockquote style="margin: 2em 0 0;padding: 0.5em 1em;border-left: 3px solid #F44336;background-color: #F5F5F5;list-style: none;">
                    <p><strong>
                         
                            <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/80x15.png" /></a><br />本作品采用<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可。
                        </strong>
                        <br>
                        <strong>本文链接：</strong><a href="https://yangshunjie.com/influxdb-in-dotNEt-Core-2-ioc-and-repository-pattern.html">https://yangshunjie.com/influxdb-in-dotNEt-Core-2-ioc-and-repository-pattern.html</a>
                    </p>
                </blockquote>
        
    

    
</div>


                

                <!-- Post Comments -->
                
                    
    <!-- 使用 Gitalk -->
<div id="gitalk-comment">
    <!-- Gitalk 评论框 -->
<div id="gitalk-container"></div>

<link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">

<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<script>
    var gitalk = new Gitalk({
            clientID: '695234dcb3266b06c9bc',
            clientSecret: '9012a4415f4672e4858df564fc9999e9b6d5cec0',
            repo: 'elderjames.github.io',
            owner: 'ElderJames',
            admin: ['ElderJames'],
            // facebook-like distraction free mode
            distractionFreeMode: false
        })
   gitalk.render('gitalk-container')
</script>
</div>
<style>
    #gitalk-comment {
        background-color: #eee;
        padding: 2pc;
    }
</style>

                
            </div>

            <!-- Post Prev & Next Nav -->
            <nav class="material-nav mdl-color-text--grey-50 mdl-cell mdl-cell--12-col">
    <!-- Prev Nav -->
    
        <a href="/A-Middleware-Implement-For-Server-Side-Static-Caching-In-AspNetCore.html" id="post_nav-newer" class="prev-content">
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_back</i>
            </button>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            新篇
        </a>
    

    <!-- Section Spacer -->
    <div class="section-spacer"></div>

    <!-- Next Nav -->
    
        <a href="/influxdb-in-dotNEt-Core-1-Introduction.html" id="post_nav-older" class="next-content">
            旧篇
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_forward</i>
            </button>
        </a>
    
</nav>

        </div>
    </div>



                    
                        <!-- Overlay For Active Sidebar -->
<div class="sidebar-overlay"></div>

<!-- Material sidebar -->
<aside id="sidebar" class="sidebar sidebar-colored sidebar-fixed-left" role="navigation">
    <div id="sidebar-main">
        <!-- Sidebar Header -->
        <div class="sidebar-header header-cover" style="background-image: url(/img/sidebar_header.png);">
    <!-- Top bar -->
    <div class="top-bar"></div>

    <!-- Sidebar toggle button -->
    <button type="button" class="sidebar-toggle mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon" style="display: initial;" data-upgraded=",MaterialButton,MaterialRipple">
        <i class="material-icons">clear_all</i>
        <span class="mdl-button__ripple-container">
            <span class="mdl-ripple">
            </span>
        </span>
    </button>

    <!-- Sidebar Avatar -->
    <div class="sidebar-image">
        <img src="https://avatars0.githubusercontent.com/u/7550366?v=4&amp;s=460" alt="James Yeung's avatar">
    </div>

    <!-- Sidebar Email -->
    <a data-toggle="dropdown" class="sidebar-brand" href="#settings-dropdown">
        shunjiey@hotmail.com
        <b class="caret"></b>
    </a>
</div>


        <!-- Sidebar Navigation  -->
        <ul class="nav sidebar-nav">
    <!-- User dropdown  -->
    <li class="dropdown">
        <ul id="settings-dropdown" class="dropdown-menu">
            
                <li>
                    <a href="mailto:shunjiey@hotmail.com" target="_blank" title="Email Me">
                        
                            <i class="material-icons sidebar-material-icons sidebar-indent-left1pc-element">email</i>
                        
                        Email Me
                    </a>
                </li>
            
        </ul>
    </li>

    <!-- Homepage -->
    
        <li id="sidebar-first-li">
            <a href="/">
                
                    <i class="material-icons sidebar-material-icons">home</i>
                
                主页
            </a>
        </li>
        
    

    <!-- Archives  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">inbox</i>
                
                    归档
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
            <li>
                <a class="sidebar_archives-link" href="/archives/2017/12/">十二月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/11/">十一月 2017<span class="sidebar_archives-count">4</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/09/">九月 2017<span class="sidebar_archives-count">5</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/08/">八月 2017<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/07/">七月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/03/">三月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/09/">九月 2016<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/07/">七月 2016<span class="sidebar_archives-count">6</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/06/">六月 2016<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/03/">三月 2016<span class="sidebar_archives-count">4</span></a></li><li><a class="sidebar_archives-link" href="/archives/2015/12/">十二月 2015<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2015/11/">十一月 2015<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2015/10/">十月 2015<span class="sidebar_archives-count">4</span></a>
            </ul>
        </li>
        
    

    <!-- Categories  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">chrome_reader_mode</i>
                
                分类
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
                <li>
                <a class="sidebar_archives-link" href="/categories/NET-Core/">.NET Core<span class="sidebar_archives-count">9</span></a></li><li><a class="sidebar_archives-link" href="/categories/DDD/">DDD<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/categories/Docker/">Docker<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/categories/Github-Pages/">Github Pages<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/categories/Hexo/">Hexo<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/categories/树莓派/">树莓派<span class="sidebar_archives-count">1</span></a>
            </ul>
        </li>
        
    

    <!-- Pages  -->
    
        <li>
            <a href="/tags.html" title="标签云">
                
                    <i class="material-icons sidebar-material-icons">local_offer</i>
                
                标签云
            </a>
        </li>
        
    
        <li>
            <a href="/timeline.html" title="时间轴">
                
                    <i class="material-icons sidebar-material-icons">list</i>
                
                时间轴
            </a>
        </li>
        
    
        <li>
            <a href="/contact.html" title="留言板">
                
                    <i class="material-icons sidebar-material-icons">forum</i>
                
                留言板
            </a>
        </li>
        
    
        <li>
            <a href="/about.html" title="关于我">
                
                    <i class="material-icons sidebar-material-icons">face</i>
                
                关于我
            </a>
        </li>
        
    
        <li>
            <a href="/gallery.html" title="相册">
                
                    <i class="material-icons sidebar-material-icons">image</i>
                
                相册
            </a>
        </li>
        
    
        <li>
            <a href="/friends.html" title="朋友">
                
                    <i class="material-icons sidebar-material-icons">people</i>
                
                朋友
            </a>
        </li>
        
    

    <!-- Article Number  -->
    
        <li>
            <a href="/archives">
                文章总数
                <span class="sidebar-badge">34</span>
            </a>
        </li>
        
    
</ul>


        <!-- Sidebar Footer -->
        <!--
I'm glad you use this theme, the development is no so easy, I hope you can keep the copyright, I will thank you so much.
If you still want to delete the copyrights, could you still retain the first one? Which namely "Theme Material"
It will not impact the appearance and can give developers a lot of support :)

很高兴您使用并喜欢该主题，开发不易 十分谢谢与希望您可以保留一下版权声明。
如果您仍然想删除的话 能否只保留第一项呢？即 "Theme Material"
它不会影响美观并可以给开发者很大的支持和动力。 :)
-->

<!-- Sidebar Divider -->


<!-- Theme Material -->


<!-- Help & Support -->
<!--

-->

<!-- Feedback -->
<!--

-->

<!-- About Theme -->
<!--

-->

    </div>

    <!-- Sidebar Image -->
    
    <span id="footer-image">
        <a href="https://ci.appveyor.com/project/ElderJames/elderjames-github-io" target="_blank" title="AppVeyor">
            <img src="https://ci.appveyor.com/api/projects/status/b0wack7uxrvifijj?svg=true" alt="AppVeyor"><!--
     --></a>
    </span>


</aside>

                    

                    
                        <!-- Footer Top Button -->
                        <div id="back-to-top" class="toTop-wrap">
    <a href="#top" class="toTop">
        <i class="material-icons footer_top-i">expand_less</i>
    </a>
</div>

                    

                    <!--Footer-->
<footer class="mdl-mini-footer" id="bottom" >
    
        <!-- Paradox Footer Left Section -->
        <div class="mdl-mini-footer--left-section sns-list">
    <!-- Twitter -->
    

    <!-- Facebook -->
    

    <!-- Google + -->
    

    <!-- Weibo -->
    

    <!-- Instagram -->
    

    <!-- Tumblr -->
    

    <!-- Github -->
    
        <a href="ElderJames" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-github">
                <span class="visuallyhidden">Github</span>
            </button><!--
     --></a>
    

    <!-- LinkedIn -->
    
        <a href="杨舜杰" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-linkedin">
                <span class="visuallyhidden">LinkedIn</span>
            </button><!--
     --></a>
    

    <!-- Zhihu -->
    
        <a href="ElderJames" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-zhihu">
                <span class="visuallyhidden">Zhihu</span>
            </button><!--
     --></a>
    

    <!-- Bilibili -->
    

    <!-- Telegram -->
    
    
    <!-- V2EX -->
    
</div>


        <!--Copyright-->
        <div id="copyright">
            Copyright&nbsp;©&nbsp;2015&nbsp;-<script type="text/javascript">var fd = new Date();document.write("&nbsp;" + fd.getFullYear() + "&nbsp;");</script>ElderJames' Blog
            
                <br>
                
                    学习/创作/分享<br /><a href="http://icp.chinaz.com/info?q=yangshunjie.com" rel="nofollow">粤ICP备15021181号-1</a>
                
            
        </div>

        <!-- Paradox Footer Right Section -->

        <!--
        I am glad you use this theme, the development is no so easy, I hope you can keep the copyright.
        It will not impact the appearance and can give developers a lot of support :)

        很高兴您使用该主题，开发不易，希望您可以保留一下版权声明。
        它不会影响美观并可以给开发者很大的支持。 :)
        -->

        <div class="mdl-mini-footer--right-section">
            <div>
                <div class="footer-develop-div">Powered by <a href="https://hexo.io" target="_blank" class="footer-develop-a">Hexo</a></div>
                <div class="footer-develop-div">Theme - <a href="https://github.com/viosey/hexo-theme-material" target="_blank" class="footer-develop-a">Material</a></div>
            </div>
        </div>
    
</footer>


                    <!-- Import JS File -->

    <script>lsloader.load("lazyload_js","/js/lazyload.min.js?1BcfzuNXqV+ntF6gq+5X3Q==", true)</script>



    <script>lsloader.load("js_js","/js/js.min.js?V/53wGualMuiPM3xoetD5Q==", true)</script>



    <script>lsloader.load("np_js","//cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js", true)</script>


<script type="text/ls-javascript" id="NProgress-script">
    NProgress.configure({
        showSpinner: true
    });
    NProgress.start();
    $('#nprogress .bar').css({
        'background': '#29d'
    });
    $('#nprogress .peg').css({
        'box-shadow': '0 0 10px #29d, 0 0 15px #29d'
    });
    $('#nprogress .spinner-icon').css({
        'border-top-color': '#29d',
        'border-left-color': '#29d'
    });
    setTimeout(function() {
        NProgress.done();
        $('.fade').removeClass('out');
    }, 800);
</script>




    
        <script>lsloader.load("sm_js","/js/smoothscroll.js?lOy/ACj5suSNi7ZVFVbpFQ==", true)</script>
    





    <!-- Busuanzi -->
    <script src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>



<!-- CommentBox -->
   <!-- GitTalk -->





<!-- UC Browser Compatible -->
<script>
	var agent = navigator.userAgent.toLowerCase();
	if(agent.indexOf('ucbrowser')>0) {
		document.write('<link rel="stylesheet" href="/css/uc.css">');
	   alert('由于 UC 浏览器使用极旧的内核，而本网站使用了一些新的特性。\n为了您能更好的浏览，推荐使用 Chrome 或 Firefox 浏览器。');
	}
</script>

<!-- Import prettify js  -->

    
        
            <script>lsloader.load("prettify_js","//cdn.bootcss.com/prettify/r298/prettify.min.js", true)</script>
        
    



<!-- Window Load -->
<!-- add class for prettify -->
<script type="text/ls-javascript" id="window-load">
    $(window).on('load', function() {
        // Post_Toc parent position fixed
        $('.post-toc-wrap').parent('.mdl-menu__container').css('position', 'fixed');
    });

    
        
            $(function() {
                $('pre').addClass('prettyprint linenums').attr('style', 'overflow:auto;');
                prettyPrint();
                })
        
    
    
</script>

<!-- MathJax Load-->


<!-- Bing Background -->

<script type="text/ls-javascript" id="Bing-Background-script">
    queue.offer(function(){
        $('body').attr('data-original', 'https://api.i-meto.com/bing?type=S');
    });
</script>


    <script type = "text/ls-javascript" id= "title-script">
        //网页当前状态判断
        var hidden, state, visibilityChange,timer;
        var leaveTitle='(●-●) 我奔溃啦~';
        var stayTitle='(*´∇｀*) 被发现啦~';
        var difaultTitle = document.title;
        var resetTime=1000
        
                leaveTitle += document.title;
                stayTitle += document.title;
        

        if (typeof document.hidden !== "undefined") {
            hidden = "hidden";
            visibilityChange = "visibilitychange";
            state = "visibilityState";
        } else if (typeof document.mozHidden !== "undefined") {
            hidden = "mozHidden";
            visibilityChange = "mozvisibilitychange";
            state = "mozVisibilityState";
        } else if (typeof document.msHidden !== "undefined") {
            hidden = "msHidden";
            visibilityChange = "msvisibilitychange";
            state = "msVisibilityState";
        } else if (typeof document.webkitHidden !== "undefined") {
            hidden = "webkitHidden";
            visibilityChange = "webkitvisibilitychange";
            state = "webkitVisibilityState";
        }
        // 添加监听器，在title里显示状态变化
        document.addEventListener(visibilityChange, function () {
           // document.title = document[state] =='visible'?stayTitle:leaveTitle ;
            if (timer!=null) clearTimeout(timer);
            if (document[state] =='visible'){
                document.title = stayTitle;
                timer=setTimeout(function(){
                    document.title=difaultTitle;
                },resetTime)
            }
            else{
                document.title = leaveTitle;
            }
        }, false);
        //初始化页面状态
        document.title = document[state] =='visible'?stayTitle:leaveTitle ;
    </script>
    

<script type="text/ls-javascript" id="lazy-load">
    // Offer LazyLoad
    queue.offer(function(){
        $('.lazy').lazyload({
            effect : 'show'
        });
    });

    // Start Queue
    $(document).ready(function(){
        setInterval(function(){
            queue.execNext();
        },200);
    });
</script>

<!-- Custom Footer -->



<script>
    (function(){
        var scriptList = document.querySelectorAll('script[type="text/ls-javascript"]')

        for (var i = 0; i < scriptList.length; ++i) {
            var item = scriptList[i];
            lsloader.runInlineScript(item.id,item.id);
        }
    })()
console.log('\n %c © Material Theme | Version: 1.5.0 | https://github.com/viosey/hexo-theme-material %c \n', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-left-radius:5px;border-bottom-left-radius:5px;', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-right-radius:5px;border-bottom-right-radius:5px;');
</script>

                </main>
            </div>
            
                
<div id="hexo-helper-live2d">
  <canvas id="live2dcanvas" width="150" height="300"></canvas>
</div>
<style>
  #live2dcanvas{
    position: fixed;
    width: 150px;
    height: 300px;
    opacity:0.7;
    right: 0px;
    z-index: 999;
    pointer-events: none;
    bottom: 60px;
  }
</style>
<script type="text/javascript" src="/live2d/device.min.js"></script>
<script type="text/javascript">
const loadScript = function loadScript(c,b){var a=document.createElement("script");a.type="text/javascript";"undefined"!=typeof b&&(a.readyState?a.onreadystatechange=function(){if("loaded"==a.readyState||"complete"==a.readyState)a.onreadystatechange=null,b()}:a.onload=function(){b()});a.src=c;document.body.appendChild(a)};
(function(){
  if((typeof(device) != 'undefined') && (device.mobile())){
    document.getElementById("live2dcanvas").style.width = '75px';
    document.getElementById("live2dcanvas").style.height = '150px';
  }else
    if (typeof(device) === 'undefined') console.error('Cannot find current-device script.');
  loadScript("/live2d/script.js", function(){loadlive2d("live2dcanvas", "/live2d/assets/tororo.model.json", 0.5);});
})();
</script>

            
        </body>
    
</html>
